home *** CD-ROM | disk | FTP | other *** search
/ Gold Medal Software 2 / Gold Medal Software Volume 2 (Gold Medal) (1994).iso / prog / asm_0_m.arj / MOUSER.ASM < prev    next >
Assembly Source File  |  1987-10-09  |  27KB  |  644 lines

  1. ;MOUSER.007 - MOUSE cursoR for the Microsoft Mouse & Compatibles - 09/87 
  2. ; -------------------------------------------------------------------------- 
  3. ; (c) OZZARD of WIS / Paul Noeldner, 510 S. Dickinson, Madison, WI 53703
  4. ;                This Software is In the Public Domaine
  5. ; OZZARD of WIS assumes no liability for any loss or damage from use of this
  6. ; program.  Use of the program constitutes agreement to this disclaimer.
  7. ; When copied or distributed, it must include this ASM code documentation.
  8. ; -------------------------------------------------------------------------- 
  9. ;                       PURPOSE
  10. ; MOUSER is dedicated to all cats (cursor arrow tappers) out there who are
  11. ; interested in seeing how nice a mouse can work in everyday PC programs.
  12. ; The feel of high-powered point-and-click mouse software, can be quickly
  13. ; realized in any scrolling-menu program by using MOUSER and a mouse -
  14. ; without high-falutin graphics or window software, or gobs of TSR memory.  
  15. ; -------------------------------------------------------------------------- 
  16. ;            ENVIRONMENT
  17. ; The MicroSoft(Tm) MOUSE.COM or MOUSE.SYS mouse driver, or a compatible 
  18. ; using the same driver protocol, must be implemented to run MOUSER.
  19. ; MOUSER then works with ANY PROGRAM that accepts cursor up/down/left/right. 
  20. ; The mouse buttons can be used for COMMON KEYS like return and escape -
  21. ; both mouse speed, and buttons, can be set via parms to suit your needs.
  22. ; -------------------------------------------------------------------------- 
  23. ;            USE
  24. ; The MOUSER defaults - average cursor speed, and RETURN/ESCAPE/BREAK buttons,
  25. ; work well in many applications.  Individuals may wish to adjust the
  26. ; speed and the button functions for particular applications, to make mouse
  27. ; use satisfying and productive (rather than tedius or target practice).
  28. ; The cursor speed and buttons can be customized by you to complement 
  29. ; your applications.  You run MOUSER with control parameters from the DOS
  30. ; prompt or in any application .bat procedure file.
  31. ; -------------------------------------------------------------------------- 
  32. ;            PARMS
  33. ; MOUSER Hn Vn Lnn Rnn Bnn?
  34. ;    ? - help - which also appears if parms are not understood
  35. ;    Hn, Vn  n=1 to 9 - sets Horizontal or Vertical cursor speed
  36. ;    Lx, Rx, Bx - x=character or 2-digit ASCII value - sets Left, 
  37. ;                    Right, or Both (pressed together) button key values
  38. ;                 Digit values above 31 are treated as 'extended' keys.
  39. ;    These parms are all optional, in any order, with any delimiters.
  40. ; -------------------------------------------------------------------------- 
  41. ;            SAMPLES
  42. ;  MOUSER ?         - shows full help, sample button ASCII values.
  43. ;  MOUSER        - sets default medium cursor, RETURN, ESCAPE buttons
  44. ;  MOUSER H1 V1 L27 R13 B/ - slow cursor, left ESCAPE, right RETURN, both /
  45. ;    This might be appropriate for a scrolling-bar menu program.
  46. ;    This example shows how to reverse the return/escape buttons,
  47. ;       if you happen to prefer them in that order.  Both buttons would
  48. ;       input a slash, which may be useful for spreadsheet commands.
  49. ;  MOUSER V9 L73 R81 B27 - fast vertical, left PGUP, right PGDN, both ESC
  50. ;    This would be useful in a text file browse, and to 
  51. ;       quickly position the cursor and mark blocks in an editor.
  52. ;   The button keys work in any program that accepts the specified keys.
  53. ;   The MOUSER ? help display shows several more common key values.    
  54. ;   See your DOS or BASIC manual for a complete list of the ASCII values
  55. ;   of keys below 32 (space), such as 13-RETURN, and the 'extended' keys
  56. ;   such as 81-PGUP.  Any values over 32 are considered 'extended' keys.
  57. ;   If a character is specified instead of a 2-digit value, it is used.
  58. ;   MOUSER +         - the + parm is the currently implemented means to 
  59. ;                reactivate MOUSER if it becomes deactivated.
  60. ;                         Once you use +, it must be used subsequently.
  61. ;                         Hopefully, the next version will not need this.
  62. ; -------------------------------------------------------------------------- 
  63. ; The regular cursor keys continue to work as usual.  Programs that have
  64. ; their own mouse driver support, work independently of MOUSER.
  65. ; MOUSER does not prevent or preclude any normal use of the keyboard.
  66. ; -------------------------------------------------------------------------- 
  67. ; Some programs appear to disable MOUSER; you may want to put MOUSER
  68. ; in the application .bat startup file, after the application program,
  69. ; to turn the mouse back on after running the application.  Programs
  70. ; that have custom mouse drivers are commonly guilty of this crime.
  71. ; In that case, use the + parameter to ask that a fresh copy be loaded.
  72. ; Once the + parameter is used, it must subsequently be used each time.
  73. ; -------------------------------------------------------------------------- 
  74. ;            MORE ABOUT TSR AND RELOADING
  75. ; Normally one copy of MOUSER loads memory resident; after that, the parms
  76. ; are updated whenever the program is run.  The program takes about 600 bytes
  77. ; of memory - much less than 'custom' mouse menus.  By not reloading
  78. ; each time it is run, it saves that much more memory for you.
  79. ; If the mouse driver has been disengaged by any program, it is reengaged
  80. ; by using the + parameter, which loads a fresh copy of MOUSER.  A future 
  81. ; version of this program should get around that requirement, but my 
  82. ; knowledge of assembler is pretty weak and I cannot seem to reengage by
  83. ; pointing at the current resident version.  Give it a hack - give me a call!
  84. ; See the code related to tsrsav and address 126h - that was my attempt.
  85. ; -------------------------------------------------------------------------- 
  86. ;            ACKNOWLEDGMENT
  87. ; The program code was modeled after MOUSEKEY by Jeff Prosise / Ziff Davis.
  88. ; -------------------------------------------------------------------------- 
  89. ;            CHANGES FROM MOUSEKEY
  90. ; While MOUSER can be used in place of MOUSEKEY, the defaults are different.
  91. ; Enhancements have been made to improve user control over parameters. 
  92. ; The program normally loads just one TSR copy even if run more than once.
  93. ; -------------------------------------------------------------------------- 
  94. ;            SPECIFIC IMPROVEMENTS 
  95. ; (1) Added control over sensitivity of horizontal motion.
  96. ; (2) Prioritized vertical above horizontal movement (otherwise the mouse
  97. ;     tends to jump left and right while positioning vertically).
  98. ; (3) Set defaults to suit menu scrolling - slower cursor speed, and
  99. ;     mouse buttons set to RETURN, ESCAPE (instead of MOUSEKEY PGUP, PGDN).
  100. ; (4) Allow optional parms for speed 1-9 and custom mouse button values
  101. ;     specified as actual characters or 2-digit ASCII codes.
  102. ;     Example:  MOUSER H5 V5 L13 R27 B03 (example indicates the defaults).
  103. ;     All parms are optional in any order.  Any delimiters are ignored.
  104. ;     Any unrecognized 'junk' on the command line displays help and a message.
  105. ; (5) Added processing for 'both buttons' pressed, giving a third key value
  106. ;     in addition to left and right button values.  Default is 03, CTRL-C.
  107. ; (5) Added help - enter MOUSER ? for help display.  
  108. ; (6) Posts current TSR version if already loaded, by finding itself in
  109. ;     memory.  This is especially important since the intent is to run 
  110. ;     MOUSER whenever it is desirable to set parms to suit particular programs.  
  111. ;     It may be run as part of .BAT files for specific applications.
  112. ;     Currently, if driver is 'disengaged', must reload using + parm.
  113. ; --------------------------------------------------------------------------
  114. ;            PROGRAM STRUCTURE
  115. ; The following program structure is based on Jeff Prosise's MOUSEKEY.
  116. ; It includes a TSR segment and an initialization segment that now sets the
  117. ; parameters and terminates after pointing the PLP to the end of the TSR part.
  118. ; If already loaded, parms are posted to the current address of the program.
  119. ; -------------------------------------------------------------------------- 
  120. bios_data     segment at 40h
  121.               org 1Ah
  122. buffer_head   dw ?                          ;pointer to keyboard buffer head
  123. buffer_tail   dw ?                          ;pointer to keyboard buffer tail
  124.               org 80h
  125. buffer_start  dw ?                          ;starting keyboard buffer address
  126. buffer_end    dw ?                          ;ending keyboard buffer address
  127. bios_data     ends
  128. ;
  129. code          segment para public 'code'
  130.               assume cs:code
  131.               org 100h
  132. begin:        jmp init                    ;goto initialization code
  133. ; -------------------------------------------------------------------------- 
  134. ;This part was enhanced in MOUSER to include hdelay and lkey/rkey/bkey values,
  135. ;and to support location and posting of current TSR version of program.
  136. ; -------------------------------------------------------------------------- 
  137. resfinder    db 'MOUSER CODE'    ;This is used to find and change parms
  138.                     ;if MOUSER program is already resident.
  139.                     ;Address of above literal is mcb+113h.
  140.                     ;If this db block is changed, also
  141.                     ;change the initialize mcb: and post: 
  142.                     ;code that finds and changes the parms.
  143.                     ;The following parms are at mcb+11Eh.
  144. vdelay        db 5            ;vertical delay (set by Vn speed parm)
  145. hdelay        db 5            ;horizontal delay (set by Hn parm)
  146. lkey        dw 000Dh        ;keycode for left button (set by Lnn)
  147. rkey        dw 001Bh        ;keycode for right button (set by Rnn)
  148. bkey        dw 0003h        ;keycode for both buttons (set by Bnn)
  149. tsrsav        dw 0000h        ;address of 'mouse' segment below
  150. ;  
  151. vcount        db 1            ;vertical mouse mickey counter
  152. hcount        db 1            ;horizontal mouse mickey counter
  153. vflag        dw ?            ;vertical count sign flag
  154. hflag        dw ?            ;horizontal count sign flag
  155. keycode        db 4Dh,4Bh,50h,48h    ;keycodes for up/dn/lf/rt cursor keys
  156. ;------------------------------------------------------------------------------
  157. ;This subroutine is handed control by the mouse driver when the mouse is
  158. ;moved or a button is pressed.
  159. ;------------------------------------------------------------------------------
  160. mouse         proc far
  161. ;
  162. ;Determine which event occurred and branch accordingly.
  163. ;
  164.               test ax,2                     ;was the left button pressed?
  165.               jnz lbut                      ;yes, then branch
  166.               test ax,8                     ;was the right button pressed?
  167.               jnz rbut                      ;yes, then branch
  168. ; -------------------------------------------------------------------------- 
  169. ;Move the cursor in the direction indicated by the most recent mouse move.
  170. ;This was modified from MOUSEKEY to prioritize vertical over horizontal,
  171. ;and to test a horizontal delay factor.
  172. ; -------------------------------------------------------------------------- 
  173. mouse0:       mov ax,11                     ;function 11
  174.               int 51                        ;read mouse motion counters
  175.               mov hflag,0                   ;initialize sign flags
  176.               mov vflag,2
  177.               xor al,al                     ;zero AL for extended keycode
  178.               cmp dx,0                      ;vertical count positive?
  179.               jge mouse1                    ;yes, then branch
  180.               inc vflag                     ;record negative condition
  181.               neg dx                        ;convert negative to positive
  182. mouse1:       cmp cx,0                      ;horizontal count positive?
  183.               jge mouse2                    ;yes, then branch
  184.               inc hflag                     ;record negative condition
  185.               neg cx                        ;convert negative to positive
  186. mouse2:       mov bx,vflag                  ;assume motion was vertical
  187.               cmp dx,cx                     ;was the assumption correct?
  188.               jae mouse4                    ;yes, then branch
  189.               mov bx,hflag                  ;no, then correct it
  190.               dec hcount                    ;decrement horizontal count
  191.               jz  mouse3                    ;continue if count is zero
  192.               ret                           ;exit if it's not
  193. ; -------------------------------------------------------------------------- 
  194. ;The hdelay/vdelay values allow control over horizontal sensitivity.
  195. ;These are input as Hn Vn parms as speed 1-slow to 9-fast, and converted
  196. ;for decrementing to delay 9-slow to 1-fast.  The delay simply ignores
  197. ;the indicated number of mickeys (mouse increments) before responding.
  198. ;They correspond roughly to screen pixels; e.g. speed 1 moves 1 pixel where
  199. ;speed 9 moves 9 pixels in a similar physical mouse movement (about 1/32").  
  200. ; -------------------------------------------------------------------------- 
  201. mouse3:       mov ah,hdelay
  202.           mov hcount,ah                 ;reset horizontal delay
  203.               jmp setkey                    ;  
  204. mouse4:       dec vcount                    ;decrement vertical delay
  205.               jz  mouse5                    ;continue if count is zero
  206.               ret                           ;exit if it's not
  207. mouse5:       mov ah,vdelay
  208.           mov vcount,ah                 ;reset vertical delay
  209. setkey:       mov ah,keycode[bx]            ;get keycode from table
  210.               jmp insert                    ;insert it into keyboard buffer
  211. ;
  212. ;The left button was pressed.  Load AX with the keycode.
  213. ;
  214. lbut:         test ax,8
  215.           jnz bbut                ;both buttons?
  216.           mov ax,lkey                   ;load left button keycode
  217.               jmp insert        ;insert into the keyboard buffer
  218. ;
  219. ;The right button was pressed.  Load AX with the keycode.
  220. ;
  221. rbut:         mov ax,rkey                   ;load keycode
  222.           jmp insert        ;insert into keyboard buffer
  223. ;
  224. ;Both buttons were pressed.  Load AX with the keycode.
  225. ;
  226. bbut:          mov ax,bkey        ;load both button keycode
  227. ;
  228. ;Insert the keycode in AX into the keyboard buffer.
  229. ;
  230. insert:       mov bx,bios_data              ;point DS to BIOS data area
  231.               mov ds,bx
  232.               assume ds:bios_data
  233.               cli                           ;disable interrupts
  234.               mov bx,buffer_tail            ;get buffer tail address
  235.               mov dx,bx                     ;transfer it to DX
  236.               add dx,2                      ;calculate next buffer position
  237.               cmp dx,buffer_end             ;did we overshoot the end?
  238.               jne insert1                   ;no, then continue
  239.               mov dx,buffer_start           ;yes, then wrap around
  240. insert1:      cmp dx,buffer_head            ;is the buffer full?
  241.               je insert2                    ;yes, then end now
  242.               mov [bx],ax                   ;insert the keycode
  243.               mov bx,dx                     ;advance the tail
  244.               mov buffer_tail,bx            ;record its new position
  245. insert2:      sti                           ;enable interrupts
  246.               assume ds:nothing
  247.               ret                           ;exit user-defined subroutine
  248. mouse         endp
  249. ;
  250. ;------------------------------------------------------------------------------
  251. ;INIT routine points the mouse driver to the user-defined subroutine,
  252. ;then leaves it resident in memory.
  253. ;------------------------------------------------------------------------------
  254. init        proc near
  255.                 jmp setup                     
  256. ;
  257. logo        db 201,205,205,181
  258. db' MOUSER.007 / 10/87 / OZZARD of WIS / Public Domain / ?-HELP '
  259. db 198,205,205,187,13,10,'$'
  260. ;
  261. helpmsg        db 186
  262. db '          Paul Noeldner, Madison, WI 608-255-5577                  '
  263. db 186,13,10,186
  264. db '   ',15,' For CATS (Cursor Arrow Tappers) with MS(tm) compatible Mice.  '
  265. db 186,13,10,186
  266. db '   ',15,' To use a mouse in any program that uses cursor arrows, just   '
  267. db 186,13,10,186
  268. db '     set the speed for easy pointing and buttons for common keys.  '
  269. db 186,13,10,186
  270. db '   ',15,' Put MOUSER into .BAT files, set for specific applications.    '
  271. db 186,13,10,186
  272. db ' MOUSER H5 V5 L13 R27 B03   Example showing default parameters.    '
  273. db 186,13,10,186
  274. db ' MOUSER H1 V2 B/            Slower cursor (for 123-style menus).   '
  275. db 186,13,10,186
  276. db ' MOUSER V9 L73 R81 B27      Faster with PGUP/PGDN (for browsing).  '
  277. db 186,13,10,186
  278. db '    Hn, Vn      Horizontal, Vertical speed 1-9, default 5-medium.  '
  279. db 186,13,10,186
  280. db '    Lx, Rx, Bx  Sets button key characters or ASCII key codes.     '
  281. db 186,13,10,186
  282. db '    +           Loads new copy of MOUSER (use only if disengaged). '
  283. db 186,13,10,186
  284. db '    All parms are optional, in any order, with any delimiters.     '
  285. db 186,13,10,186
  286. db '    Button ASCII key values over 31 are used for extended keys.    '
  287. db 186,13,10,186
  288. db '    These are commonly used keys (see a BASIC manual for more):    '
  289. db 186,13,10,186
  290. db '       03 - CTRL/C   09 - TAB     13 - RETURN   27 - ESCAPE        '
  291. db 186,13,10,186
  292. db '       71 - HOME     73 - PGUP    79 - END      81 - PGDN          '
  293. db 186,13,10,186
  294. db '       82 - INSERT   83 - DELETE  59 THRU 68 - F1 THRU F10         '
  295. db 186,13,10,200
  296. db 67 dup ('═')
  297. db 188,13,10,'$'
  298. ;
  299. errmsg      db 7,200
  300. db 8 dup ('═')
  301. db 16,' DRIVER MISSING: Install MOUSE.SYS or MOUSE.COM ',17
  302. db 9 dup ('═')
  303. db 188,7,13,10,'$'
  304. ;
  305. junkmsg      db 7,200
  306. db 7 dup ('═')
  307. db 16,' UKNOWN INPUT PARAMETER - CHECK THIS HELP DISPLAY ',17
  308. db 8 dup ('═')
  309. db 188,7,'$'
  310. ;
  311. loadmsg        db 200
  312. db 18 dup ('═')
  313. db 16,' OK - Mouse Cursor Installed ',17
  314. db 18 dup ('═')
  315. db 188,13,10,'$'
  316. ;
  317. postmsg        db 200
  318. db 16 dup ('═')
  319. db 16,' OK - Mouse Cursor Parms Adjusted ',17
  320. db 15 dup ('═')
  321. db 188,13,10,'$'
  322. ;
  323. endparm     dw 81h        ;end of parm input
  324. mcbptr        dw 0000h    ;pointer to memory control blocks
  325. found           db 'N'        ;is MOUSER already loaded TSR in memory
  326. newcopy        db 'N'        ;indicates if + (update) parm entered
  327. lit        db ?        ;literal parm input character
  328. dig        db 'N'        ;found a digit?
  329. ;
  330. ;Logo display
  331. ;
  332. setup:    lea dx,logo              ;show logo
  333.     mov ah,9                
  334.     int 21h                 
  335.     call parms        ;process input parms
  336.     call mcbwalk        ;check if MOUSER is already resident 
  337. endit:    jmp allthru        ;exit program
  338. ;
  339. init    endp
  340. ;
  341. ;-----------------------------------------------------------------------------
  342. ;Process the command line parms (if any)
  343. ;
  344. parms    proc near
  345.     mov bx,0        ;point at input parm length in Pgm Seg Prefix
  346.     mov si,80h        
  347.     mov ah,0
  348.         mov al,byte ptr[si]     ;now we have the length 
  349.     add ax,80h        ;compute end of parm
  350.         mov endparm,ax          ;remember it
  351.     inc si            ;skip initial space in input parm
  352. ;
  353. parmloop:
  354.     mov bx,0
  355.     inc si            ;get input from command parm
  356.     cmp si,endparm             ;see if at end of parm
  357.         jle parse        ;if not, process it
  358.     ret            ;if so, done with setup work
  359. ;
  360. parse:    mov al,byte ptr[si]    ;get next character
  361.         cmp al,' '        ;skip blanks
  362.     je  parmloop
  363.     cmp al,'/'        ;skip slashes
  364.     je  parmloop
  365.     cmp al,','        ;skip commas
  366.     je  parmloop
  367.     cmp al,'+'        ;load new copy?
  368.     jne help
  369.     mov newcopy,'Y'        
  370.     jmp parmloop
  371. help:    cmp al,'?'        ;show help?
  372.     jne case
  373.     lea dx,helpmsg        ;help display
  374.     mov ah,9
  375.     int 21h
  376.     int 20h
  377. ;
  378. case:     cmp al,91        ;upper case?
  379.     jl  upper
  380.           sub al,32        ;convert lower to upper case   
  381. ;
  382. upper:    call parmcheck        ;see if H, V, L, R 
  383.     jmp parmloop        ;continue parsing thru parm
  384. ;
  385. parms    endp
  386. ;
  387. ;-----------------------------------------------------------------------------
  388. ;Check for Horizontal and Vertical Speed, Left/Right/Both button control values
  389. ;
  390. parmcheck proc near
  391.     cmp al,'H'        ;is it horizontal speed parm
  392.     jne parmv               ;if not, check vertical speed
  393.     call digedit        ;check it out, value returned in al
  394.         cmp dig,'Y'        ;is it a digit?
  395.         jne junk        ;if not, return message
  396.     not al            ;invert 10-speed to get delay
  397.       mov hdelay,al           ;store horizontal delay value 
  398.     ret            ;back to parsing parms
  399. ;
  400. parmv:    cmp al,'V'        ;is it vertical speed parm?
  401.     jne parml               ;if not, check left button
  402.     call digedit        ;check it out, value returned in al
  403.     cmp dig,'Y'        ;is it a digit?
  404.     jne junk        ;if not, return message
  405.     not al            ;invert 10-speed to get delay
  406.     mov vdelay,al           ;store vertical delay value 
  407.     ret        
  408. ;
  409. parml:    cmp al,'L'        ;is it left button parm?
  410.     jne parmr               ;if not, check right button
  411.         call dighex        ;get digits into hex
  412.     mov lkey,ax        ;set left button key code
  413.     ret        
  414. ;
  415. parmr:    cmp al,'R'        ;is it right button parm?
  416.     jne parmb        ;if not,check both buttons
  417.     call dighex        ;get digits into hex
  418.     mov rkey,ax        ;set right button key code
  419.     ret
  420. ;
  421. parmb:    cmp al,'B'        ;is it both buttons parm?
  422.     jne junk        ;send message if unknown parm 
  423.     call dighex        ;get digits into hex
  424.     mov bkey,ax        ;set both buttons key code
  425.     ret
  426. ;
  427. ;Junk parm error message
  428. ;
  429. junk:    lea dx,helpmsg        ;help, plus error message for invalid parms
  430.     mov ah,9
  431.     int 21h
  432.     lea dx,junkmsg        
  433.     mov ah,9
  434.     int 21h
  435.     int 20h            ;and program ends
  436. ;
  437. parmcheck endp
  438. ;
  439. ;-----------------------------------------------------------------------------
  440. ;Digits to hex routine
  441. dighex    proc near
  442.     call digedit        ;get next digit
  443.         cmp dig,'Y'        ;is it a digit?
  444.     je  digcon         ;if so, continue
  445.     ret            ;otherwise got literal, return it
  446. digcon:    cbw            ;byte in al goes to word in ax
  447.     xchg ax,bx        ;trade digit and number
  448.     mov cx,10d
  449.     mul cx            ;number in ax times 10
  450.     xchg ax,bx        ;trade number and digit
  451.     add bx,ax        ;add digit to number
  452.     call digedit        ;get next digit
  453.     cmp dig,'Y'        ;is it a digit?
  454.     jne junk        ;return message if not
  455.     cbw            ;byte in al goes to word in ax
  456.     xchg ax,bx        ;trade digit and number
  457.     mov cx,10d
  458.     mul cx            ;number in ax times 10
  459.     xchg ax,bx        ;trade number and digit
  460.     add bx,ax        ;add digit to number
  461.         mov ax,bx   
  462.         cmp al,20h        ;is number > 20?
  463.     jl setok        ;no, set as is
  464.     mov ah,al        ;yes, make it high byte
  465.     mov al,0        ;null low byte
  466. setok:    ret            ;all thru, got 2 digits into binary form
  467. ;
  468. dighex endp
  469. ;
  470. ;-----------------------------------------------------------------------------
  471. ;Get value of ASCII digit or literal, return in ah
  472. ;
  473. digedit    proc near
  474.     mov dig,'N'        ;may not have a digit here
  475.     inc si            
  476.     mov al,byte ptr[si]    ;get next byte
  477.         mov lit,al        ;save literal value
  478.     sub al,30h        ;drop ascii code to convert digit to value
  479.     jl  liter        ;if not digit, use literal
  480.     cmp al,9d        ;
  481.     jg  liter        ;if not digit, use literal
  482.      sub al,11d
  483.     mov dig,'Y'        ;yes, got a digit
  484.     ret
  485. liter:    or ax,ax        ;get ax to null
  486.     mov al,lit        ;plug in literal character
  487.     ret            ;back to parm scan
  488. ;
  489. digedit endp
  490. ;
  491. ;-----------------------------------------------------------------------------
  492. ;See if MOUSER is already resident by walking memory control blocks.
  493. ;
  494. ;Each MCB is marked with M in first byte, last block has Z in first byte.
  495. ;The length of each MCB is in byte 3.  Adding len + 1 locates the next MCB.
  496. ;If MOUSER is already resident, parms are updated in that copy of the program.
  497. ;
  498. mcbwalk proc near
  499.     push bp            ;remember right where we were (we hope)
  500.     push ax                 ;the stack was getting messed in this code
  501.     push bx
  502.     push cx
  503.     push dx
  504.     push ds
  505.     push es
  506.     mov ah,52h        ;DOS fn to get first memory control block
  507.     int 21h            
  508.     mov ax,es:[bx-2]    ;stash starting mcb address in variable
  509.     mov mcbptr,ax
  510. ;
  511. search: mov es,mcbptr        ;get first byte at current mcb address
  512.     mov dl,byte ptr es:[0]
  513.         cmp dl,'M'        ;an M means TSR, but not last one loaded
  514.         je  gotmcb
  515.     pop es
  516.     pop ds
  517.     pop dx
  518.     pop cx
  519.     pop bx
  520.     pop ax
  521.     pop bp            ;back to current memory values and pointers
  522.         ret            ;Done with TSR chain
  523. ;
  524. gotmcb: cmp found,'Y'        ;see if already found
  525.     je  nextmcb        ;skip to end of chain if already found
  526.     mov dl,byte ptr es:[113h] ;if not found yet, look for 'MOUSER CODE'
  527.     cmp dl,'M'          ;literal starting in byte 4
  528.     jne nextmcb
  529.     mov dl,byte ptr es:[114h]
  530.     cmp dl,'O'
  531.     jne nextmcb
  532.     mov dl,byte ptr es:[115h]
  533.     cmp dl,'U'
  534.     jne nextmcb
  535.     mov dl,byte ptr es:[116h]
  536.     cmp dl,'S'
  537.     jne nextmcb
  538.     mov dl,byte ptr es:[117h]
  539.     cmp dl,'E'
  540.     jne nextmcb
  541.     mov dl,byte ptr es:[118h]
  542.     cmp dl,'R'
  543.     jne nextmcb
  544.     mov dl,byte ptr es:[11Ah]
  545.     cmp dl,'C'
  546.     jne nextmcb
  547.     mov dl,byte ptr es:[11Bh]
  548.     cmp dl,'O'
  549.     jne nextmcb
  550.     mov dl,byte ptr es:[11Ch]
  551.     cmp dl,'D'
  552.     jne nextmcb
  553.     mov dl,byte ptr es:[11Dh]
  554.     cmp dl,'E'
  555.     jne nextmcb
  556.     call post        ;post parms to existing MOUSER TSR copy
  557.     jmp nextmcb
  558. ;
  559. nextmcb: mov ax,mcbptr        ;on to the next mcb
  560.     mov es,ax
  561.     add ax,word ptr es:3    ;length of block is in byte 3
  562.         inc ax            ;add length plus 1 for next mcbptr
  563.     mov mcbptr,ax
  564.         jmp search
  565. ;
  566. mcbwalk endp
  567. ;
  568. ;-----------------------------------------------------------------------------
  569. ;Post parms to data locations in current resident version of MOUSER
  570. ;
  571. post    proc near
  572.     mov found,'Y'        ;indicate TSR now found
  573.     mov al,vdelay        ;and post V, H, L, R and B parms to memory
  574.      mov byte ptr es:[11Eh],al
  575.     mov al,hdelay
  576.     mov byte ptr es:[11Fh],al
  577.     mov ax,lkey
  578.     mov word ptr es:[120h],ax
  579.     mov ax,rkey
  580.     mov word ptr es:[122h],ax
  581.     mov ax,bkey
  582.     mov word ptr es:[124h],ax
  583. ;
  584. ;The following code should re-activate the mouse driver addressability
  585. ;to the currently loaded tsr mouse routine we just found.  
  586. ;It is commented out because the code as written here leaves the mouse
  587. ;driver pointing into never-never land somewhere.  Please help me Peter Pan!
  588. ;
  589. ;    mov ax,12                     ;function 12, set ms driver active
  590. ;    mov cx,11                     ;subroutine call mask
  591. ;    mov dx,word ptr es:[126h]     ;offset of tsrsav pointer to mouse seg
  592. ;    int 51                        ;pass information to mouse driver
  593.      ret
  594. ;
  595. post    endp
  596. ;
  597. ;-----------------------------------------------------------------------------
  598. ;If MOUSER already TSR, end normally, else end TSR
  599. ;
  600. allthru proc
  601.     cmp found,'Y'
  602.     jne tsr
  603.     cmp newcopy,'Y'
  604.     je  tsr
  605.      mov ah,9        ;send post message
  606.     lea dx,postmsg
  607.     int 21h  
  608.     int 20h            ;normal exit to DOS
  609. ;
  610. tsr:    call msmouse        ;make sure mouse driver is resident
  611.     mov ah,9        ;send load message
  612.     lea dx,loadmsg
  613.     int 21h
  614.     mov ax,12        ;function 12, set ms driver active
  615.     mov cx,11        ;subroutine call mask (bits 1011)
  616.                 ;call if mouse moved, or button tapped
  617.     mov dx,offset mouse    ;point ES:DX to the TSR subroutine
  618.     mov tsrsav,dx        ;and save this address for later use
  619.     int 51            ;pass address to mouse driver
  620.     lea dx,init        ;point DX to end of resident code
  621.     int 27h            ;terminate-but-stay-resident
  622. ;
  623. allthru endp
  624. ;
  625. ;-----------------------------------------------------------------------------
  626. ;Make sure the ms mouse hardware and software are in place.
  627. ;
  628. msmouse proc near
  629.     mov ax,0                      ;function 0
  630.     int 51                        ;get installation flag
  631.     or ax,ax                      ;is AX zero?
  632.     jne msok                      ;proceed with loading
  633.     mov ah,9                      ;print error message and abort
  634.     lea dx,errmsg
  635.     int 21h
  636.     int 20h
  637. ;
  638. msok:    ret            ;continue loading
  639. ;
  640. msmouse endp
  641. code    ends
  642.         end begin
  643.